# _*_ coding:utf-8 _*_
# @Time  : 2022.11.07
# @Author: zizlee

# 图形数据对比解读
import json
import pandas as pd
import numpy as np
from fastapi import APIRouter, Query
from v1_all_api.all_response import AllResponse
from v1_all_api.all_utils import datalib_utils, datetime_utils
from db import FAConnection

chart_compare_api = APIRouter()


@chart_compare_api.get('/chartCompare/')
async def chart_compare_description(cid: int = Query(..., ge=1), compare: str = Query(...)):
    db_conn = FAConnection()
    # 查询图形信息
    chart_obj = db_conn.query("SELECT * FROM datalib_variety_chart WHERE id=%s LIMIT 1;", [cid], fetchone=True)[0]
    # 获取数据
    indication = json.loads(chart_obj['indication'])  # 需要的指标
    chart_option = json.loads(chart_obj['options'])  # 图形配置空壳
    df, headers = await datalib_utils.get_index_formula_dataframe(column_templates=indication, na_fill=np.NAN,
                                                                  start_date=chart_obj['startdate'],
                                                                  end_date=chart_obj['enddate'])
    # 对比解读
    headers = list(filter(lambda x: x['isChecked'], headers))
    if compare == 'day':  # 日环比
        lr_df = df.tail(5)
        lr_df['compare'] = lr_df['datadate'].apply(lambda x: x.strftime('%Y%m%d'))
        df['compare'] = df['datadate'].apply(lambda x: x.strftime('%Y%m%d'))
    elif compare == 'week':
        lr_df = df.tail(21)  # 取3周数据运算
        lr_df['compare'] = lr_df['datadate'].apply(lambda x: x.strftime('%Y%W'))
        df['compare'] = df['datadate'].apply(lambda x: x.strftime('%Y%W'))
    elif compare == 'month':
        lr_df = df.tail(93)  # 取3个月运算
        lr_df['compare'] = lr_df['datadate'].apply(lambda x: x.strftime('%Y%m'))
        df['compare'] = df['datadate'].apply(lambda x: x.strftime('%Y%m'))
    elif compare == 'quarter':
        lr_df = df.tail(279)  # 取3个季度运算
        lr_df['compare'] = lr_df['datadate'].apply(lambda x: datetime_utils.get_quarter(x))
        df['compare'] = df['datadate'].apply(lambda x: datetime_utils.get_quarter(x))
    elif compare == 'annual':
        lr_df = df.tail(800)  # 取大于2年运算
        lr_df['compare'] = lr_df['datadate'].apply(lambda x: x.year)
        df['compare'] = df['datadate'].apply(lambda x: x.year)
    else:
        return AllResponse.operate_successfully({
            'compare': compare,
            'link_ratios': [],
            'chart_option': chart_option
        })
    # 分析环比数据
    lr_df = lr_df.fillna(method='ffill')
    lr_df = lr_df.sort_values(by='compare')
    lr_df = lr_df.groupby('compare', as_index=False).last()
    link_ratios = []
    for col in headers:
        lr_df['link_ratio'] = lr_df[col['prop']].pct_change().round(4)
        lr_df['_link_ratio_symbol_'] = lr_df[col['prop']].shift(1).apply(lambda x: -1 if x < 0 else 1)
        lr_df['link_ratio'] = lr_df['link_ratio'] * lr_df['_link_ratio_symbol_']
        del lr_df['_link_ratio_symbol_']
        lr_df = lr_df.replace([np.inf, -np.inf], np.nan)  # 替代无穷大为nan
        lr_df = lr_df.fillna('')  # 替代nan为''
        link_ratios.append({
            'name': col['name'],
            'unit': col['unit'],
            'datadate': lr_df.iloc[-1]['datadate'],
            'datavalue': lr_df.iloc[-1][col['prop']],
            'link_ratio': lr_df.iloc[-1]['link_ratio'],
        })
    # 处理图形配置数据
    df = df.groupby('compare', as_index=False).last()
    df['datadate'] = df['datadate'].apply(lambda x: x.strftime(chart_obj['xaxis_format']))
    # 1. xAxisData 2. series 3. legendData
    if chart_obj['chart_type'] == 'season':  # 季节图形
        # 取出作图列的prop
        prop_name = ''
        for i_item in indication:
            if i_item['isChecked']:
                prop_name = i_item['prop']
                break
        x_axis_data = datetime_utils.date_of_year()
        # 数据源按年分组
        df['year'] = df['datadate'].apply(lambda x: x[:4])
        df['date'] = df['datadate'].apply(lambda x: x[5:])
        series = []
        legend_data = []
        for year_group in df.groupby(by='year').groups:
            y_df = pd.merge(pd.DataFrame(data=x_axis_data, columns=['date']), df[df['year'] == year_group],
                            on='date',
                            how='left')
            # y_df.fillna(None, inplace=True)
            series.append({
                'symbol': 'none', 'connectNulls': True, 'name': year_group,
                'type': 'line', 'yAxisIndex': 0,
                'data': list(map(lambda x: None if pd.isna(x[prop_name]) else x[prop_name], y_df.to_dict(orient='records')))
            })
            legend_data.append({'name': year_group})
    else:  # 普通图形
        chart_source_data = df.to_dict(orient='records')
        x_axis_data = list(map(lambda x: x['datadate'], chart_source_data))
        series = []
        legend_data = []
        for i_item in indication:
            if i_item['isChecked']:
                o_series = {'symbol': 'none', 'connectNulls': True, 'name': i_item['name'],
                            'type': i_item['chartType'], 'yAxisIndex': i_item['yIndex'],
                            'data': list(map(lambda x: None if pd.isna(x[i_item['prop']]) else x[i_item['prop']], chart_source_data))}
                series.append(o_series)
                legend_data.append({'name': i_item['name']})
    # 放入具体的配置中
    chart_option['xAxis'][0]['data'] = x_axis_data
    chart_option['series'] = series
    chart_option['legend']['data'] = legend_data
    # 十字光标 原来有tooltip={trigger:axis}
    chart_option['tooltip']['axisPointer'] = {'type': 'cross'}
    # 颜色
    chart_option['color'] = ['#5b9bd5', '#ed7d31', '#ffc000', '#4472c4', '#70ad47', '#255e91',
                             '#9e480e', '#636363', '#997300', '#264478', '#43682b', '#7cafdd',
                             '#f1975a', '#ffcd33', '#698ed0', '#8cc168', '#327dc2', '#d26012']
    # 标题居中
    chart_option['title']['left'] = 'center'
    # 放入当前请求图形的id
    chart_option['chart_id'] = cid
    response_data = {
        'compared': compare,
        'link_ratios': link_ratios,
        'chart_option': chart_option,
    }
    return AllResponse.operate_successfully(data=response_data)
